import json

from .Fields import FieldVisitor, Record, RecordVisitor
from .visitorbase import Element, Visitor


class Block(Element):
    Type = ''

    # FieldLine = Row()

    def __init__(self, fieldrow):
        self.FieldNameRecord = Record(0, fieldrow)

    def iter_fields(self, exclude=None, only=None):
        """This method iterates over all fields that are defined and yields
        ``(key, value)`` tuples.  Per default all fields are returned, but
        it's possible to limit that to some fields by providing the `only`
        parameter or to exclude some using the `exclude` parameter.  Both
        should be sets or tuples of field names.
        """
        for name in self.FieldNameRecord:
            if (
                    (exclude is only is None)
                    or (exclude is not None and name not in exclude)
                    or (only is not None and name in only)
            ):
                try:
                    yield name
                    # , getattr(self, name)
                except AttributeError:
                    pass

    def iter_child_nodes(self, exclude=None, only=None):
        """Iterates over all direct child nodes of the node.  This iterates
        over all fields and yields the values of they are nodes.  If the value
        of a field is a list all the nodes in that list are returned.
        """
        # for _, item in self.iter_fields(exclude, only):
        #     if isinstance(item, list):
        #         for n in item:
        #             if isinstance(n, Node):
        #                 yield n
        #     elif isinstance(item, Node):
        #         yield item


class BlockRecs(Block):
    def __init__(self, fieldrow):
        super().__init__(fieldrow)
        self.ValueRecords = []

    def add(self, row):
        if row.type != 'BlankLine':
            rec = Record(row.index, row, self.FieldNameRecord)
            # rec.setFieldRow(self.FieldNameRecord)
            self.ValueRecords.append(rec)

    def iter_records(self):
        for line in self.ValueRecords:
            yield line.accept(RecordVisitor())


class BlockConfig(BlockRecs):

    def __init__(self, fieldrow, valuerow):
        super().__init__(fieldrow)
        # self.FieldLine = fieldrow

        self.add(valuerow)

    def iter_values(self):
        # 返回  {'name':'NAME', 'xxx':'XXX' ... }

        # from .visitorpartern import FieldVisitor
        # for name, id in self.FieldRow.iter_fields():
        #     yield name, str(self.ValueRow[id])
        for name, id in self.FieldNameRecord.iter_fields():
            # yield name, FieldVisitor().toDict(self.ValueRecords[0][id], {})
            yield name, self.ValueRecords[0][id].accept(FieldVisitor())

    def toDict(self):
        return self.ValueRecords[0].accept(RecordVisitor())


class BlockRecords(BlockRecs):
    pass


class BlockTestcases(BlockRecs):
    pass


class BlockVisitor(Visitor):
    def visit(self, element):
        # # 根据节点名获取对应处理方法
        # meth_name = 'visit_' + type(element).__name__
        # # 将获取到的方法绑定到 meth
        # meth = getattr(self, meth_name, None)
        # # 如果没有对应方法，则将回退方法绑定到 meth
        # if meth is None:
        #     meth = element.accept(self)
        # # 返回 meth 方法调用的结果
        # return meth(element)

        return self.visitByName(element)

    def visit_BlockConfig(self, element):
        return {'config': element.toDict()}
        # return 'config', element.toDict()  # dict(element.iter_values())

    def visit_BlockRecords(self, element):
        dd = []
        for xx in element.iter_records():
            dd.append(dict(xx))

        return {'teststeps': dd}
        # return 'teststeps', dd

    def visit_BlockTestcases(self, element):
        dd = []
        for xx in element.iter_records():
            dd.append(dict(xx))

        return {'testcases': dd}
        # return 'teststeps', dd

class TC_Blocks_rec:
    """测试用例结构
        config   records
    """

    def __init__(self):
        self.config = None
        self.tcrecords = None

    def to_dict(self):
        visitor = BlockVisitor()
        d1 = self.config.accept(visitor)
        d2 = self.tcrecords.accept(visitor)

        return {**d1, **d2}

        # cname, cvalue = self.config.accept(visitor)   # BlockVisitor().visit(self.config)
        # rname, rvalue = self.tcrecords.accept(visitor)   # BlockVisitor().visit(self.tcrecords)
        # return {cname: cvalue,
        #         rname: rvalue}

    def finejson(self):
        jj = self.to_dict()
        ojson = json.dumps(jj, skipkeys=False, check_circular=True, allow_nan=True,
                           indent=4, separators=(',', ':'), ensure_ascii=False)

        return ojson

    def display(self):
        print(self.finejson())

    def create_config(self, fieldrow, valuerow):
        self.config = BlockConfig(fieldrow, valuerow)
        return self.config

    def _create_recs(self, recs, totalcount, func_cindex, func_nextvalues):
        self.tcrecords = recs
        while func_cindex() + 1 < totalcount:
            self.tcrecords.add(func_nextvalues())

        return self.tcrecords

    def create_record(self, totalcount, func_cindex, func_nextvalues):
        return self._create_recs(BlockRecords(func_nextvalues()),
                                 totalcount, func_cindex, func_nextvalues)

        # self.tcrecords = BlockRecords(func_nextvalues())
        # while func_cindex() + 1 < totalcount:
        #     self.tcrecords.add(func_nextvalues())
        #
        # return self.tcrecords

    def create_testcases(self, totalcount, func_cindex, func_nextvalues):
        return self._create_recs(BlockTestcases(func_nextvalues()),
                                 totalcount, func_cindex, func_nextvalues)
        # self.tcrecords = BlockTestcases(func_nextvalues())
        # while func_cindex() + 1 < totalcount:
        #     self.tcrecords.add(func_nextvalues())
        #
        # return self.tcrecords
